home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / ansipas.zip / ANSIIO.PAS < prev    next >
Pascal/Delphi Source File  |  1990-08-14  |  23KB  |  556 lines

  1.  
  2. UNIT AnsiIO;
  3.  
  4. INTERFACE
  5.  
  6.    USES
  7.       CRT,
  8.       Graph3;
  9.  
  10.    FUNCTION ANSIClrScr : string;
  11.    FUNCTION ANSIClrEol : string;
  12.    FUNCTION ANSIGotoXY(X, Y : word) : string;
  13.    FUNCTION ANSIUp(Lines : word) : string;
  14.    FUNCTION ANSIDown(Lines : word) : string;
  15.    FUNCTION ANSIRight(Cols : word) : string;
  16.    FUNCTION ANSILeft(Cols : word) : string;
  17.    FUNCTION ANSIColor(Fg, Bg : integer) : string;
  18.    FUNCTION ANSIMusic(s : string) : string;
  19.    PROCEDURE ANSIWrite(s : string);
  20.    PROCEDURE ANSIWriteLn(s : string);
  21.  
  22. IMPLEMENTATION
  23.  
  24.    CONST
  25.       ColorArray : array[0..7] of integer = (0,4,2,6,1,5,3,7);
  26.  
  27.    VAR
  28.       Bold, TruncateLines : boolean;
  29.       Vari, Octave, Numb : integer;
  30.       Test, Dly, Intern, DlyKeep : longInt;
  31.       Flager, ChartoPlay : char;
  32.       Typom, Min1, Adder : real;
  33.  
  34. {****************************************************************************}
  35. {***                                                                      ***}
  36. {***       Function that returns the ANSI code for a Clear Screen.        ***}
  37. {***                                                                      ***}
  38. {****************************************************************************}
  39.    FUNCTION ANSIClrScr : string;
  40.       BEGIN
  41.          ANSIClrScr := #27+'[2J';
  42.       END;
  43.  
  44. {****************************************************************************}
  45. {***                                                                      ***}
  46. {***    Function that returns the ANSI code for a Clear to End of Line.   ***}
  47. {***                                                                      ***}
  48. {****************************************************************************}
  49.    FUNCTION ANSIClrEol : string;
  50.       BEGIN
  51.          ANSIClrEol := #27+'[K';
  52.       END;
  53.  
  54. {****************************************************************************}
  55. {***                                                                      ***}
  56. {***   Function that returns the ANSI code to move the cursor to (X,Y).   ***}
  57. {***                                                                      ***}
  58. {****************************************************************************}
  59.    FUNCTION ANSIGotoXY(X, Y : word) : string;
  60.       VAR
  61.          XStr, YStr : string;
  62.  
  63.       BEGIN
  64.          str(X,XStr);
  65.          str(Y,YStr);
  66.          ANSIGotoXY := #27+'['+YStr+';'+XStr+'H';
  67.       END;
  68.  
  69. {****************************************************************************}
  70. {***                                                                      ***}
  71. {***  Function that returns the ANSI code to move the cursor up "Lines"   ***}
  72. {***                         number of lines.                             ***}
  73. {***                                                                      ***}
  74. {****************************************************************************}
  75.    FUNCTION ANSIUp(Lines : word) : string;
  76.       VAR
  77.          LinesStr : string;
  78.  
  79.       BEGIN
  80.          str(Lines,LinesStr);
  81.          ANSIUp := #27+'['+LinesStr+'A';
  82.       END;
  83.  
  84. {****************************************************************************}
  85. {***                                                                      ***}
  86. {***  Function that returns the ANSI code to move the cursor down "Lines" ***}
  87. {***                        number of lines.                              ***}
  88. {***                                                                      ***}
  89. {****************************************************************************}
  90.    FUNCTION ANSIDown(Lines : word) : string;
  91.       VAR
  92.          LinesStr : string;
  93.  
  94.       BEGIN
  95.          str(Lines,LinesStr);
  96.          ANSIDown := #27+'['+LinesStr+'B';
  97.       END;
  98.  
  99. {****************************************************************************}
  100. {***                                                                      ***}
  101. {***     Function that returns the ANSI code to move the cursor "Cols"    ***}
  102. {***                         positions forward.                           ***}
  103. {***                                                                      ***}
  104. {****************************************************************************}
  105.    FUNCTION ANSIRight(Cols : word) : string;
  106.       VAR
  107.          ColsStr : string;
  108.  
  109.       BEGIN
  110.          str(Cols,ColsStr);
  111.          ANSIRight := #27+'['+ColsStr+'C';
  112.       END;
  113.  
  114. {****************************************************************************}
  115. {***                                                                      ***}
  116. {***     Function that returns the ANSI code to move the cursor "Cols"    ***}
  117. {***                        positions backward.                           ***}
  118. {***                                                                      ***}
  119. {****************************************************************************}
  120.    FUNCTION ANSILeft(Cols : word) : string;
  121.       VAR
  122.          ColsStr : string;
  123.  
  124.       BEGIN
  125.          str(Cols,ColsStr);
  126.          ANSILeft := #27+'['+ColsStr+'D';
  127.       END;
  128.  
  129.  
  130. {****************************************************************************}
  131. {***                                                                      ***}
  132. {***    Function that returns the ANSI code to change the screen color    ***}
  133. {***             to an "Fg" foreground and a "Bg" background.             ***}
  134. {***                                                                      ***}
  135. {****************************************************************************}
  136.    FUNCTION ANSIColor(Fg, Bg : integer) : string;
  137.       VAR
  138.          FgStr, BgStr, Temp : string;
  139.  
  140.       BEGIN
  141.          str(ColorArray[Fg mod 8] + 30, FgStr);
  142.          str(ColorArray[Bg mod 8] + 40, BgStr);
  143.          Temp := #27+'[';
  144.          if Bg > 7 then
  145.             Temp := Temp+'5;'
  146.          else
  147.             Temp := Temp+'0;';
  148.          if Fg > 7 then
  149.             Temp := Temp+'1;'
  150.          else
  151.             Temp := Temp+'2;';
  152.          ANSIColor := Temp+FgStr+';'+BgStr+'m';
  153.       END;
  154.  
  155. {****************************************************************************}
  156. {***                                                                      ***}
  157. {*** Function that returns an ANSI code representing a music string ("s") ***}
  158. {***                                                                      ***}
  159. {****************************************************************************}
  160.    FUNCTION ANSIMusic(s : string) : string;
  161.  
  162.       BEGIN
  163.          ANSIMusic := #27+'[MF'+s+#14;
  164.       END;
  165.  
  166. {****************************************************************************}
  167. {***                                                                      ***}
  168. {***  Procedure that simulates BASIC's "PLAY" procedure.  Will also work  ***}
  169. {***      with ANSI codes.  Taken from PC Magazine Volume 9 Number 3      ***}
  170. {***                                                                      ***}
  171. {****************************************************************************}
  172.    PROCEDURE Play(SoundC : string);
  173.       FUNCTION IsNumber(ch : char) : boolean;
  174.          BEGIN
  175.             IsNumber := (CH >= '0') AND (CH <= '9');
  176.          END;
  177.  
  178.    {Converts a string to an integer}
  179.       FUNCTION value(s : string) : integer;
  180.          VAR
  181.             ss, sss : integer;
  182.          BEGIN
  183.             Val(s, ss, sss);
  184.             value := ss;
  185.          END;
  186.  
  187.    {Plays the selected note}
  188.       PROCEDURE sounder(key : char; flag : char);
  189.          VAR
  190.             old, New, new2 : Real;
  191.          BEGIN
  192.             adder := 1;
  193.             old := dly;
  194.             New := dly;
  195.             intern := Pos(key, 'C D EF G A B')-1;
  196.             IF (flag = '+') AND (key <> 'E') AND (key <> 'B') {See if note}
  197.                THEN Inc(intern);                              {is sharped }
  198.             IF (flag = '-') AND (key <> 'F') AND (key <> 'C')
  199.                THEN Dec(intern);                              {or a flat. }
  200.             WHILE SoundC[vari+1] = '.' DO
  201.                BEGIN
  202.                   Inc(vari);
  203.                   adder := adder/2;
  204.                   New := New+(old*adder);
  205.                END;
  206.             new2 := (New/typom)*(1-typom);
  207.             sound(Round(Exp((octave+intern/12)*Ln(2)))); {Play the note}
  208.             Delay(Trunc(New));
  209.             Nosound;
  210.             Delay(Trunc(new2));
  211.          END;
  212.  
  213.    {Calculate delay for a specified note length}
  214.       FUNCTION delayer1 : integer;
  215.          BEGIN
  216.             numb := value(SoundC[vari+1]);
  217.             delayer1 := Trunc((60000/(numb*min1))*typom);
  218.          END;
  219.  
  220.    {Used as above, except reads a number >10}
  221.  
  222.       FUNCTION delayer2 : Integer;
  223.          BEGIN
  224.             numb := value(SoundC[vari+1]+SoundC[vari+2]);
  225.             delayer2 := Trunc((60000/(numb*min1))*typom);
  226.          END;
  227.  
  228.       BEGIN                           {Play}
  229.          SoundC := SoundC+' ';
  230.          FOR vari := 1 TO Length(SoundC) DO
  231.             BEGIN                     {Go through entire string}
  232.                SoundC[vari] := Upcase(SoundC[vari]);
  233.                CASE SoundC[vari] OF
  234. {Check to see}    'C','D','E',
  235. {if char is a}    'F','G','A',
  236. {note}            'B' : BEGIN
  237.                            flager := ' ';
  238.                            dlykeep := dly;
  239.                            chartoplay := SoundC[vari];
  240.                            IF (SoundC[vari+1] = '-') OR
  241.                               (SoundC[vari+1] = '+') THEN
  242. {Check for flats & sharps}    BEGIN
  243.                                  flager := SoundC[vari+1];
  244.                                  Inc(vari);
  245.                               END;
  246.                            IF IsNumber(SoundC[vari+1]) THEN
  247.                               BEGIN
  248.                                  IF IsNumber(SoundC[vari+2]) THEN
  249.                                     BEGIN
  250.                                        test := delayer2;
  251. {Make sure # is legal}                 IF numb < 65 THEN
  252.                                           dly := test;
  253.                                        Inc(vari, 2);
  254.                                     END
  255.                                  ELSE
  256.                                     BEGIN
  257.                                        test := delayer1;
  258. {Make sure # is legal}                 IF numb > 0 THEN
  259.                                           dly := test;
  260.                                        Inc(vari);
  261.                                     END;
  262.                               END;
  263.                            sounder(chartoplay, flager);
  264.                            dly := dlykeep;
  265.                         END;
  266. {Check for}       'O' : BEGIN
  267. {octave change}            Inc(vari);
  268.                            CASE SoundC[vari] OF
  269.                               '-' : IF octave > 1 THEN Dec(octave);
  270.                               '+' : IF octave < 7 THEN Inc(octave);
  271.                               '1','2','3',
  272.                               '4','5','6',
  273.                               '7' : octave := value(SoundC[vari])+4;
  274.                            ELSE Dec(vari);
  275.                            END;
  276.                         END;
  277. {Check for a}     'L' : IF IsNumber(SoundC[vari+1]) THEN
  278. {change in length}         BEGIN
  279. {for notes}                   IF IsNumber(SoundC[vari+2]) THEN
  280.                                  BEGIN
  281.                                     test := delayer2;
  282.                                     IF numb < 65 THEN
  283. {Make sure # is legal}                 dly := test;
  284.                                     Inc(vari, 2);
  285.                                  END
  286.                               ELSE
  287.                                  BEGIN
  288.                                     test := delayer1;
  289.                                     IF numb > 0 THEN
  290. {Make sure # is legal}                 dly := test;
  291.                                     Inc(vari);
  292.                                  END;
  293.                            END;
  294. {Check for pause} 'P' : IF IsNumber(SoundC[vari+1]) THEN
  295. {and it's length}          BEGIN
  296.                               IF IsNumber(SoundC[vari+2]) THEN
  297.                                  BEGIN
  298.                                     test := delayer2;
  299.                                     IF numb < 65 THEN
  300. {Make sure # is legal}                 Delay(test);
  301.                                     Inc(vari, 2);
  302.                                  END
  303.                               ELSE
  304.                                  BEGIN
  305.                                     test := delayer1;
  306.                                     IF numb > 0 THEN
  307. {Make sure # is legal}                 Delay(test);
  308.                                     Inc(vari);
  309.                                  END;
  310.                            END;
  311. {Check for}       'T' : IF IsNumber(SoundC[vari+1]) AND
  312. {tempo change}             IsNumber(SoundC[vari+2]) THEN
  313.                            BEGIN
  314.                               IF IsNumber(SoundC[vari+3]) THEN
  315.                                  BEGIN
  316.                                     min1 := value(SoundC[vari+1]+
  317.                                             SoundC[vari+2]+SoundC[vari+3]);
  318.                                     Inc(vari, 3);
  319.                                     IF min1 > 255 THEN
  320. {Make sure # isn't too big}            min1 := 255;
  321.                                  END
  322.                               ELSE
  323.                                  BEGIN
  324.                                     min1 := value(SoundC[vari+1]+
  325.                                             SoundC[vari+2]);
  326.                                     IF min1 < 32 THEN
  327. {Make sure # isn't too small}          min1 := 32;
  328.                                  END;
  329.                               min1 := min1/4;
  330.                            END;
  331. {Check for music} 'M' : BEGIN
  332. {type}                     Inc(vari);
  333.                            CASE Upcase(SoundC[vari]) OF
  334. {Normal}                      'N' : typom := 7/8;
  335. {Legato}                      'L' : typom := 1;
  336. {Staccato}                    'S' : typom := 3/4;
  337.                            END;
  338.                         END;
  339.                END;
  340.             END;
  341.       END;
  342.  
  343. {****************************************************************************}
  344. {***                                                                      ***}
  345. {***    Procedure to process string "s" and write its contents to the     ***}
  346. {***          screen, interpreting ANSI codes as it goes along.           ***}
  347. {***                                                                      ***}
  348. {****************************************************************************}
  349.    PROCEDURE ANSIWrite(s : string);
  350.       VAR
  351.          SaveX, SaveY : byte;
  352.          MusicStr : string;
  353.          MusicPos : integer;
  354.  
  355.    {*** Procedure to process the actual ANSI sequence ***}
  356.       PROCEDURE ProcessEsc;
  357.          VAR
  358.             DeleteNum : integer;
  359.             ts : string[5];
  360.             Num : array[0..10] of shortint;
  361.             Color : integer;
  362.  
  363.          LABEL
  364.             loop;
  365.  
  366.       {*** Procedure to extract a parameter from the ANSI sequence and ***}
  367.       {*** place it in "Num" ***}
  368.          PROCEDURE GetNum(cx : byte);
  369.             VAR
  370.                code : integer;
  371.             BEGIN
  372.                ts := '';
  373.                WHILE (s[1] in ['0'..'9']) and (length(s) > 0) DO
  374.                   BEGIN
  375.                      ts := ts + s[1];
  376.                      Delete(s,1,1);
  377.                   END;
  378.                val(ts,Num[cx],code)
  379.             END;
  380.  
  381.          BEGIN
  382.             IF s[2] <> '[' THEN exit;
  383.             Delete(s,1,2);
  384.             IF (UpCase(s[1]) = 'M') and (UpCase(s[2]) in ['F','B']) THEN
  385. {play music}   BEGIN
  386.                   Delete(s,1,2);
  387.                   MusicPos := pos(#14,s);
  388.                   Play(copy(s,1,MusicPos-1));
  389.                   DeleteNum := MusicPos;
  390.                   Goto Loop;
  391.                END;
  392.             fillchar(Num,sizeof(Num),#0);
  393.             GetNum(0);
  394.             DeleteNum := 1;
  395.             WHILE (s[1] = ';') and (DeleteNum < 11) DO
  396.                BEGIN
  397.                   Delete(s,1,1);
  398.                   GetNum(DeleteNum);
  399.                   DeleteNum  := DeleteNum + 1;
  400.                END;
  401.             CASE UpCase(s[1]) of
  402. {move up}      'A' : BEGIN
  403.                         if Num[0] = 0 THEN
  404.                            Num[0] := 1;
  405.                         WHILE Num[0] > 0 DO
  406.                            BEGIN
  407.                               GotoXY(wherex,wherey - 1);
  408.                               Num[0] := Num[0] - 1;
  409.                            END;
  410.                         DeleteNum := 1;
  411.                      END;
  412. {move down}    'B' : BEGIN
  413.                         if Num[0] = 0 THEN
  414.                            Num[0] := 1;
  415.                         WHILE Num[0] > 0 DO
  416.                            BEGIN
  417.                               GotoXY(wherex,wherey + 1);
  418.                               Num[0] := Num[0] - 1;
  419.                            END;
  420.                         DeleteNum := 1;
  421.                      END;
  422. {move right}   'C' : BEGIN
  423.                         if Num[0] = 0 THEN
  424.                            Num[0] := 1;
  425.                         WHILE Num[0] > 0 DO
  426.                            BEGIN
  427.                               GotoXY(wherex + 1,wherey);
  428.                               Num[0] := Num[0] - 1;
  429.                            END;
  430.                         DeleteNum := 1;
  431.                      END;
  432. {move left}    'D' : BEGIN
  433.                         if Num[0] = 0 THEN
  434.                            Num[0] := 1;
  435.                         WHILE Num[0] > 0 DO
  436.                            BEGIN
  437.                               GotoXY(wherex - 1,wherey);
  438.                               Num[0] := Num[0] - 1;
  439.                            END;
  440.                         DeleteNum := 1;
  441.                      END;
  442. {goto x,y}     'H',
  443.                'F' : BEGIN
  444.                         if (Num[0] = 0) THEN
  445.                            Num[0] := 1;
  446.                         if (Num[1] = 0) THEN
  447.                            Num[1] := 1;
  448.                         GotoXY(Num[1],Num[0]);
  449.                         DeleteNum := 1;
  450.                      END;
  451. {save current} 'S' : BEGIN
  452. {position}              SaveX := wherex;
  453.                         SaveY := wherey;
  454.                         DeleteNum := 1;
  455.                      END;
  456. {restore}      'U' : BEGIN
  457. {saved position}        GotoXY(SaveX,SaveY);
  458.                         DeleteNum := 1;
  459.                      END;
  460. {clear screen} 'J' : BEGIN
  461.                         if Num[0] = 2 THEN
  462.                            ClrScr;
  463.                         DeleteNum := 1;
  464.                      END;
  465. {clear from}   'K' : BEGIN
  466. {cursor position}       ClrEOL;
  467. {to end of line}        DeleteNum := 1;
  468.                      END;
  469. {change}       'M' : BEGIN
  470. {colors and}            DeleteNum := 0;
  471. {attributes}            WHILE (Num[DeleteNum] <> 0) or (DeleteNum = 0) DO
  472.                            BEGIN
  473.                               CASE Num[DeleteNum] of
  474. {all attributes off}             0 : BEGIN
  475.                                         NormVideo;
  476.                                         Bold := false;
  477.                                      END;
  478. {bold on}                        1 : Bold := true;
  479. {blink on}                       5 : textattr := textattr + blink;
  480. {reverse on}                     7 : textattr := ((textattr and $07) shl 4) +
  481.                                      ((textattr and $70) shr 4);
  482. {invisible on}                   8 : textattr := 0;
  483. {general foregrounds}            30..
  484.                                  37 : BEGIN
  485.                                          color := ColorArray[Num[DeleteNum]
  486.                                                   - 30];
  487.                                          IF Bold THEN
  488.                                             color := color + 8;
  489.                                          textcolor(color);
  490.                                       END;
  491. {general backgrounds}            40..
  492.                                  47 : textbackground(
  493.                                       ColorArray[Num[DeleteNum] - 40]);
  494.                               END;
  495.                               DeleteNum := DeleteNum + 1;
  496.                            END;
  497.                         DeleteNum := 1;
  498.                      END;
  499. {change text}  '=',
  500. {modes}        '?' : BEGIN
  501.                         Delete(s,1,1);
  502.                         GetNum(0);
  503.                         if UpCase(s[1]) = 'H' THEN
  504.                            BEGIN
  505.                               CASE Num[0] of
  506.                                  0 : TextMode(bw40);
  507.                                  1 : TextMode(co40);
  508.                                  2 : TextMode(bw80);
  509.                                  3 : TextMode(co80);
  510.                                  4 : GraphColorMode;
  511.                                  5 : GraphMode;
  512.                                  6 : HiRes;
  513.                                  7 : TruncateLines := false;
  514.                               END;
  515.                            END;
  516.                         if UpCase(s[1]) = 'L' THEN
  517.                            if Num[0] = 7 THEN
  518.                               TruncateLines := true;
  519.                         DeleteNum := 1;
  520.                      END;
  521.             END;
  522. loop:       Delete(s,1,DeleteNum);
  523.          END;
  524.  
  525.       BEGIN
  526.          WHILE length(s) > 0 DO
  527.             BEGIN
  528.                if s[1] = #27 THEN
  529.                   ProcessEsc
  530.                else
  531.                   BEGIN
  532.                      Write(s[1]);
  533.                      Delete(s,1,1);
  534.                   END;
  535.             END;
  536.       END;
  537.  
  538. {****************************************************************************}
  539. {***                                                                      ***}
  540. {***         Procedure that calls ANSIWrite, then line feeds.             ***}
  541. {***                                                                      ***}
  542. {****************************************************************************}
  543.    PROCEDURE ANSIWriteLn(s : string);
  544.       BEGIN
  545.          ANSIWrite(s);
  546.          WriteLn;
  547.       END;
  548.  
  549.    BEGIN
  550.       Octave := 4;
  551.       ChartoPlay := 'N';
  552.       Typom := 7/8;
  553.       Min1 := 120;
  554.       TruncateLines := false;
  555.    END.
  556.